home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / st80_pr4.lha / st80_pre4 / Foible / foible / Icon-Tools.st < prev    next >
Text File  |  1993-07-24  |  21KB  |  760 lines

  1. 'From Tektronix Smalltalk-80 version T2.2.0cM3, of September 21, 1987 on 3 May 1990 at 3:26:27 pm'!
  2.  
  3. BitEditor subclass: #IconEditor
  4.     instanceVariableNames: ''
  5.     classVariableNames: ''
  6.     poolDictionaries: ''
  7.     category: 'Icon-Tools'!
  8. IconEditor comment:
  9. 'I am the icon editor that IconManager uses to edit its icons.  I have an 
  10. unscheduled view.  A real-size view of the icon displayed in my palette.'!
  11.  
  12. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  13.  
  14. IconEditor class
  15.     instanceVariableNames: ''!
  16.  
  17.  
  18. !IconEditor class methodsFor: 'editing forms'!
  19.  
  20. editIcon: anIcon
  21.     "Bit editing of an area of the display screen. User designates a 
  22.     rectangular area that is magnified by 8 to allow individual screens dots to be 
  23.     modified.  Editor is not scheduled in a view.  Original screen location is 
  24.     updated immediately."
  25.  
  26.     | scaleFactor tempRect |
  27.     scaleFactor _ 8 @ 8.
  28.     tempRect _ self locateMagnifiedView: anIcon scale: scaleFactor.
  29.     "show magnified form size until mouse is depressed"
  30.     self
  31.         openScreenViewOnForm: anIcon
  32.         magnifiedAt: tempRect topLeft 
  33.         scale: scaleFactor! !
  34.  
  35.  
  36. !IconEditor class methodsFor: 'instance creation'!
  37.  
  38. openScreenViewOnForm: aForm magnifiedAt: magnifiedLocation scale: scaleFactor
  39.     "Create and schedule a BitEditor on the form aForm"
  40.  
  41.     | bitEditor savedForm |
  42.     bitEditor _ self bitEdit: aForm at: magnifiedLocation scale: scaleFactor remoteView: nil.
  43.     savedForm _ Form fromDisplay: (Rectangle origin: bitEditor labelDisplayBox topLeft corner: bitEditor displayBox corner).
  44.     bitEditor controller blueButtonMenu: nil blueButtonMessages: nil.
  45.     bitEditor controller startUp.
  46.     savedForm displayOn: Display at: bitEditor labelDisplayBox topLeft.
  47.     bitEditor release! !
  48.  
  49.  
  50. !IconEditor class methodsFor: 'class initialization'!
  51.  
  52. initialize
  53.     "IconManager initialize."
  54.  
  55.     YellowButtonMenu _ PopUpMenu labels:
  56. 'accept
  57. cancel'.
  58.     YellowButtonMessages _ #(accept cancel)! !
  59.  
  60.  
  61. IconEditor initialize!
  62.  
  63.  
  64. ScrollController subclass: #IconEditorController
  65.     instanceVariableNames: 'bottomScrollBar bottomMarker bottomSavedArea '
  66.     classVariableNames: ''
  67.     poolDictionaries: ''
  68.     category: 'Icon-Tools'!
  69. IconEditorController comment:
  70. 'I am the controller for IconView. We are used in an icon browser to 
  71. provide a view of the icon.  I implement the ability to scroll the view of
  72. the icon both horizontally and vertically.'!
  73.  
  74.  
  75. !IconEditorController methodsFor: 'initialize-release'!
  76.  
  77. initialize
  78.  
  79.     super initialize.
  80.     bottomScrollBar _ Quadrangle new.
  81.     bottomScrollBar borderWidthLeft: 2 right: 2 top: 0 bottom: 2.
  82.     bottomMarker _ Quadrangle new.
  83.     bottomMarker insideColor: Form gray.! !
  84.  
  85.  
  86. !IconEditorController methodsFor: 'control sequence'!
  87.  
  88. controlInitialize
  89.  
  90.     super controlInitialize.
  91.     bottomScrollBar region: (0@0 extent: (view displayBox width + 2) @ 32).
  92.     bottomMarker region: self computeBottomMarkerRegion.
  93.     bottomScrollBar _ bottomScrollBar align:  bottomScrollBar topLeft with: view displayBox bottomLeft - (1@0).
  94.     bottomMarker _ bottomMarker align: bottomMarker leftCenter with: bottomScrollBar inside leftCenter.
  95.     bottomSavedArea _ Form fromDisplay: bottomScrollBar.
  96.     bottomScrollBar displayOn: Display.
  97.     self moveBottomMarker!
  98.  
  99. controlTerminate
  100.     super controlTerminate.
  101.     bottomSavedArea notNil
  102.         ifTrue:
  103.             [bottomSavedArea displayOn: Display at: bottomScrollBar topLeft.
  104.               bottomSavedArea _ nil ]! !
  105.  
  106.  
  107. !IconEditorController methodsFor: 'scrolling'!
  108.  
  109. bottomScroll
  110.     "Check to see whether the user wishes to jump, scroll left, or scroll right."
  111.  
  112.     | savedCursor regionPercent |
  113.     savedCursor _ sensor currentCursor.
  114.     [self bottomScrollBarContainsCursor]
  115.         whileTrue: 
  116.             [Processor yield.
  117.             regionPercent _ 100 * ( bottomScrollBar inside bottom - sensor cursorPoint y  ) // bottomScrollBar height.
  118.             regionPercent <= 40
  119.                 ifTrue: [self scrollLeft]
  120.                 ifFalse: [regionPercent >= 60
  121.                             ifTrue: [self scrollRight]
  122.                             ifFalse: [self bottomScrollAbsolute]]].
  123.     savedCursor show!
  124.  
  125. bottomScrollAmount
  126.  
  127.     ^ ((view inverseDisplayTransform: sensor cursorPoint)
  128.         - (view inverseDisplayTransform: bottomScrollBar inside leftCenter ))  x!
  129.  
  130. bottomScrollView
  131.  
  132.     
  133.   self bottomScrollView: self bottomViewDelta!
  134.  
  135. bottomScrollView: anInteger
  136.     | maximumAmount minimumAmount amount |
  137.     maximumAmount _
  138.         view clippingRectangle left -
  139.         view compositionRectangle left max: 0.
  140.     minimumAmount _
  141.         view clippingRectangle right -
  142.         view compositionRectangle right min: 0.
  143.     amount _
  144.         (anInteger min: maximumAmount) max:
  145.         minimumAmount.
  146.     amount ~= 0
  147.         ifTrue:
  148.             [view scrollBy: amount@0]!
  149.  
  150. bottomViewDelta
  151.     ^view clippingRectangle left - view compositionRectangle left - 
  152.         ((  bottomMarker left -  bottomScrollBar inside left  ) asFloat /
  153.             bottomScrollBar inside width asFloat * 
  154.                 view compositionRectangle width asFloat )   rounded!
  155.  
  156. canBottomScroll
  157.     ^ (bottomMarker region width < bottomScrollBar inside width)!
  158.  
  159. canScrollDown
  160.     ^self canScroll and: [marker region top > scrollBar inside top]!
  161.  
  162. canScrollLeft
  163.     ^self canBottomScroll and: [bottomMarker region right < bottomScrollBar inside right]!
  164.  
  165. canScrollRight
  166.     ^self canBottomScroll and: [bottomMarker region left > bottomScrollBar inside left]!
  167.  
  168. canScrollUp
  169.     "Answer whether there is information that is not visible and can be seen
  170.     by scrolling up."
  171.     ^self canScroll and: [marker region bottom < scrollBar inside bottom]!
  172.  
  173. scrollView: anInteger
  174.     | maximumAmount minimumAmount amount |
  175.     maximumAmount _
  176.         view clippingRectangle top -
  177.         view compositionRectangle top max: 0.
  178.     minimumAmount _
  179.         view clippingRectangle bottom -
  180.         view compositionRectangle bottom min: 0.
  181.     amount _
  182.         (anInteger min: maximumAmount) max:
  183.         minimumAmount.
  184.     amount ~= 0
  185.         ifTrue:
  186.             [view scrollBy: 0@amount ]!
  187.  
  188. scrollViewLeft
  189.  
  190.     self bottomScrollView: self bottomScrollAmount negated!
  191.  
  192. scrollViewRight
  193.  
  194.     self bottomScrollView: self bottomScrollAmount!
  195.  
  196. viewDelta
  197.     ^(view clippingRectangle top -
  198.             view compositionRectangle top -
  199.             ((marker top - scrollBar inside top) asFloat /
  200.                 scrollBar inside height asFloat *
  201.                 view compositionRectangle height asFloat)) rounded! !
  202.  
  203.  
  204. !IconEditorController methodsFor: 'private'!
  205.  
  206. bottomScrollAbsolute
  207.     |  oldBottomMarker  |
  208.  
  209.     self changeCursor:  Cursor up.
  210.     self canBottomScroll & sensor anyButtonPressed  ifTrue:
  211.         [[sensor anyButtonPressed ]  whileTrue:
  212.             [oldBottomMarker _ bottomMarker.
  213.               bottomMarker _ bottomMarker translateBy:
  214.                 ((sensor cursorPoint x - bottomMarker center x
  215.                  min:  bottomScrollBar inside right - bottomMarker right)
  216.                  max:  bottomScrollBar inside left - bottomMarker left) @ 0.
  217.                 (oldBottomMarker areasOutside: bottomMarker ) , 
  218.                 ( bottomMarker areasOutside:  oldBottomMarker ) do:
  219.  
  220.                     [ :region | Display fill: region rule: Form reverse
  221.                      mask: Form gray ].  self bottomScrollView ].
  222.  
  223.                 bottomScrollBar display.
  224.                 self moveBottomMarker ]!
  225.  
  226. scrollAbsolute
  227.     | oldMarker |
  228.     self changeCursor: Cursor marker.
  229.     self canScroll & sensor anyButtonPressed ifTrue:
  230.         [[sensor anyButtonPressed] whileTrue:
  231.             [ oldMarker _ marker.
  232.             marker _ marker translateBy:
  233.                 0@((sensor cursorPoint y - marker center y min:
  234.                     scrollBar inside bottom - marker bottom) max: scrollBar inside top - marker top).
  235.             (oldMarker areasOutside: marker), (marker areasOutside: oldMarker) do:
  236.                 [:region | Display fill: region rule: Form reverse mask: Form gray]. self scrollView].
  237.             scrollBar display.
  238.             self moveMarker]!
  239.  
  240. scrollLeft
  241.     | delay | 
  242.     self changeCursor: (Cursor marker rotateBy: 2) "up left".
  243.     delay _ Delay forMilliseconds: self scrollDelayLength.
  244.     self canScrollLeft ifTrue: [[sensor anyButtonPressed]
  245.             whileTrue: [self canScrollLeft
  246.                     ifTrue: 
  247.                         [self scrollViewLeft.
  248.                         self moveBottomMarker].
  249.                     delay wait]]!
  250.  
  251. scrollRight
  252.     | delay | 
  253.     self changeCursor: Cursor marker "right".
  254.     delay _ Delay forMilliseconds: self scrollDelayLength.
  255.     self canScrollRight ifTrue: [[sensor anyButtonPressed]
  256.             whileTrue: [self canScrollRight
  257.                     ifTrue: 
  258.                         [self scrollViewRight.
  259.                         self moveBottomMarker].
  260.                     delay wait]]!
  261.  
  262. scrollUp
  263.     "Scroll the text up a relative amount.  Don't go faster than the user's reaction time."
  264.     | delay | 
  265.     self changeCursor: Cursor up.
  266.     delay _ Delay forMilliseconds: self scrollDelayLength.
  267.     self canScrollUp ifTrue: [[sensor anyButtonPressed]
  268.             whileTrue: [self canScrollUp
  269.                     ifTrue: 
  270.                         [self scrollViewUp.
  271.                         self moveMarker].
  272.                     delay wait]]! !
  273.  
  274.  
  275. !IconEditorController methodsFor: 'cursor'!
  276.  
  277. bottomMarkerContainsCursor
  278.  
  279.     ^ bottomMarker inside containsPoint: sensor cursorPoint!
  280.  
  281. bottomScrollBarContainsCursor
  282.  
  283.     ^ bottomScrollBar inside  containsPoint: sensor cursorPoint! !
  284.  
  285.  
  286. !IconEditorController methodsFor: 'control defaults'!
  287.  
  288. controlActivity
  289.  
  290.     self bottomScrollBarContainsCursor
  291.         ifTrue: [self bottomScroll ]
  292.         ifFalse: [super controlActivity ]!
  293.  
  294. isControlActive
  295.  
  296.     ^ self bottomScrollBarContainsCursor | super isControlActive! !
  297.  
  298.  
  299. !IconEditorController methodsFor: 'marker adjustment'!
  300.  
  301. bottomMarkerDelta
  302.  
  303.     ^ bottomMarker left
  304.         - bottomScrollBar inside left
  305.         - (( view insetDisplayBox left - view compositionRectangle left) asFloat
  306.             / model form width asFloat * 
  307.                 bottomScrollBar inside width asFloat) rounded!
  308.  
  309. bottomMarkerRegion: aRectangle
  310.  
  311.     Display fill: bottomMarker mask: bottomScrollBar insideColor.
  312.     bottomMarker region: aRectangle.
  313.     bottomMarker _ bottomMarker align: bottomMarker leftCenter   with: bottomScrollBar inside leftCenter!
  314.  
  315. computeBottomMarkerRegion
  316.  
  317.     ^ 0@0 extent: (( view insetDisplayBox width asFloat /
  318.             model form width * bottomScrollBar inside width) rounded 
  319.             min: bottomScrollBar inside width) @ 10!
  320.  
  321. computeMarkerRegion
  322.     "Answer the rectangular area in which the gray area of the scroll bar
  323.     should be displayed."
  324.     ^0@0 extent: 10 @
  325.             ((view insetDisplayBox height asFloat /
  326.                         model form height *
  327.                             scrollBar inside height)
  328.                  rounded min: scrollBar inside height)!
  329.  
  330. markerDelta
  331.     ^marker top 
  332.         - scrollBar inside top  
  333.         - ((view insetDisplayBox top - view compositionRectangle top) asFloat 
  334.             / model form height asFloat *
  335.                 scrollBar inside height asFloat) rounded!
  336.  
  337. moveBottomMarker
  338.  
  339.     self moveBottomMarker: self bottomMarkerDelta negated!
  340.  
  341. moveBottomMarker: anInteger
  342.  
  343.     Display fill: bottomMarker mask: bottomScrollBar insideColor.
  344.     bottomMarker _ bottomMarker translateBy:  ( (anInteger 
  345.            min: bottomScrollBar inside right - bottomMarker right)
  346.            max: bottomScrollBar inside left - bottomMarker left) @ 0  .
  347.  
  348.     bottomMarker displayOn: Display! !
  349.  
  350.  
  351. !IconEditorController methodsFor: 'scroll bar region'!
  352.  
  353. repaintUnderBottomScrollBar
  354.  
  355.     bottomSavedArea notNil
  356.         ifTrue: 
  357.             [ bottomSavedArea displayOn: Display at: bottomScrollBar topLeft.
  358.                bottomSavedArea _ nil ]!
  359.  
  360. repaintUnderScrollBar
  361.  
  362.     super repaintUnderScrollBar.
  363.     self repaintUnderBottomScrollBar! !
  364.  
  365.  
  366. Object subclass: #IconManager
  367.     instanceVariableNames: 'iconDict currentIcon directory '
  368.     classVariableNames: ''
  369.     poolDictionaries: ''
  370.     category: 'Icon-Tools'!
  371. IconManager comment:
  372. 'I am an interface to editing,creating and retreiving icons stored on disk.  
  373. An icon browser can be created with my class method openOnDir:.  See 
  374. the method newIconExtent in "accessing" for defining the size of newly 
  375. created icon.
  376.  
  377. I also have a class method, getIcon: fromDirectory:, that is used by other 
  378. classes, to retrieve their icons, so that they do not have to be hard-coded 
  379. in their initialize method.
  380.  
  381. NOTE: 
  382. Several of my methods have a ''/'' hardcoded in for use when dealing with 
  383. directories.  This only works in a Unix-like environment.  DOS or Mac
  384. users will have to change the character appropriately.
  385.  
  386.  
  387. My instance variables, which are only used when I create an icon browser, are:
  388.  
  389.     iconDict         dictionary that keeps track of icons, once in memory
  390.     currentIcon     the name of the currently selected icon
  391.     directory        the directory that I am managing'!
  392.  
  393.  
  394. !IconManager methodsFor: 'accessing'!
  395.  
  396. currentIcon
  397.     ^currentIcon!
  398.  
  399. dirFullName
  400.     ^directory fullName!
  401.  
  402. form
  403.     " return the form for the current icon. if I have not read the form in from disk,
  404.       then read it in and store it in my dictionary "
  405.  
  406.     | theIcon |
  407.     currentIcon=nil ifTrue:[^Form extent: 1@1].
  408.     theIcon_iconDict at: currentIcon.
  409.     theIcon isNil
  410.         ifTrue:[theIcon_Form readFrom: self pathToCurrent.
  411.                 iconDict at: currentIcon put: theIcon].
  412.     ^theIcon!
  413.  
  414. icon: aName
  415.  
  416.     currentIcon_aName.
  417.     self changed: #form!
  418.  
  419. iconList
  420.  
  421.     iconDict isNil ifTrue: [^nil]
  422.         ifFalse: [^iconDict keys asSortedCollection]!
  423.  
  424. newIconExtent   
  425.     "return the size of new icons that are added to the library"
  426.  
  427.     ^40@50!
  428.  
  429. pathToCurrent
  430.      "return the full path to the current icon"
  431.  
  432.     ^self dirFullName,currentIcon! !
  433.  
  434.  
  435. !IconManager methodsFor: 'initialize/release'!
  436.  
  437. initDict: aDirName
  438.     " set up the dictionary of icons, ignore *.bak files "
  439.  
  440.     directory _ Disk directoryNamed: aDirName.
  441.     directory exists 
  442.         ifFalse: [PopUpNotifier message:  'Error: directory does not exist'.
  443.                   ^nil].
  444.     iconDict _ Dictionary new.
  445.     directory namesDo: 
  446.         [:each | ('*.bak' match: each)
  447.                     ifFalse: [(iconDict at: each ifAbsent: [nil]) isNil
  448.                                 ifTrue: [iconDict at: each put: nil]]]! !
  449.  
  450.  
  451. !IconManager methodsFor: 'menu'!
  452.  
  453. addIcon
  454.  
  455.     | newIcon iconName fullName|
  456.     iconName_FillInTheBlank request: 'New Icon Name' initialAnswer: ('').
  457.     iconName='' ifTrue: [^self].
  458.     iconDict isNil ifTrue: [iconDict_Dictionary new].
  459.     fullName_self dirFullName,iconName.
  460.     (FileStream fileNamed: fullName) exists
  461.         ifFalse:[newIcon_Form extent: self newIconExtent.
  462.                 newIcon writeOn: fullName]
  463.         ifTrue:[PopUpNotifier message: 'An icon with this name already exists in this directory'.
  464.                 ^nil].
  465.     iconDict at: iconName put: newIcon.
  466.     currentIcon_iconName.
  467.     self changed: #icon!
  468.  
  469. changeDir
  470.  
  471.     | newDir fullName |
  472.     newDir _ FillInTheBlank request: 'New Directory:' initialAnswer: (self dirFullName).
  473.     newDir = '' ifTrue: [^nil].
  474.     (Disk directoryNamed: newDir) exists 
  475.         ifFalse: [PopUpNotifier message:  'directory ',newDir,' does not exist'.
  476.                   ^nil].
  477.     self initDict: newDir.
  478.     self changed: #icon!
  479.  
  480. copyIcon
  481.  
  482.     | copyDir fullName |
  483.     copyDir _ FillInTheBlank request: 'Directory to Copy Icon to:' initialAnswer: (self dirFullName).
  484.     copyDir = '' ifTrue: [^self].
  485.     (Disk directoryNamed: copyDir) exists 
  486.         ifFalse: [PopUpNotifier message:  'directory ',copyDir,' does not exist'.
  487.                   ^nil].
  488.     copyDir _ copyDir,'/',currentIcon.
  489.     iconDict isNil ifTrue: [iconDict _ Dictionary new].
  490.     fullName _ self pathToCurrent.
  491.     directory copy: fullName to: copyDir!
  492.  
  493. editIcon
  494.  
  495.     | theIcon |
  496.     theIcon_iconDict at: currentIcon.
  497.     IconEditor editIcon: theIcon.
  498.     theIcon writeOn: self pathToCurrent.
  499.     self changed: #form!
  500.  
  501. iconMenu
  502.     " the menu changes depending on whether an icon is selected or not"
  503.  
  504.     currentIcon=nil
  505.         ifTrue:[^ActionMenu labels: 'add new icon
  506. change directory
  507. update icon list' withCRs 
  508.         selectors: #(addIcon changeDir updateList)].
  509.     ^ActionMenu
  510.          labels: 'add new icon
  511. edit icon
  512. icon code
  513. rename icon
  514. remove icon
  515. copy icon
  516. change directory
  517. update icon list' withCRs 
  518.         selectors: #(addIcon editIcon openCodeView renameIcon removeIcon copyIcon changeDir updateList)!
  519.  
  520. openCodeView
  521.     "Open a window with a code description of the currently displayed icon"
  522.  
  523.     | aStream |
  524.     aStream _ WriteStream on: (String new: 1000).
  525.     self form storeOn: aStream base: 10.
  526.     StringHolderView open: (StringHolder new contents: aStream contents)
  527.         label: 'Code for ',currentIcon!
  528.  
  529. removeIcon    
  530.  
  531.     | file |
  532.     file _ Disk file: self pathToCurrent.
  533.     (file exists and: [(BinaryChoice message: 'Are you sure that you want to delete ',currentIcon,'?')])
  534.         ifTrue:[file remove.
  535.                 iconDict removeKey: currentIcon.
  536.                 currentIcon_nil.
  537.                 self changed: #icon]!
  538.  
  539. renameIcon
  540.     
  541.     | newName fullName file |
  542.     newName_FillInTheBlank request: 'New Icon Name' initialAnswer: (currentIcon).
  543.     newName='' ifTrue: [^self].
  544.     fullName_ self dirFullName,newName.
  545.     (FileStream fileNamed: fullName) exists
  546.         ifTrue:[PopUpNotifier message: 'An icon with this name already exists in this directory'.
  547.                 ^nil].
  548.     (iconDict at:currentIcon) writeOn: fullName.
  549.     iconDict at: newName put: (iconDict at: currentIcon).
  550.     iconDict removeKey: currentIcon.
  551.     file _ Disk file: self pathToCurrent.
  552.     file exists ifTrue:[file remove].
  553.     currentIcon_newName.
  554.     self changed: #icon!
  555.  
  556. updateList
  557.     " update the listing of the directory"
  558.  
  559.     self initDict: self dirFullName.
  560.     self changed: #icon! !
  561.  
  562. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  563.  
  564. IconManager class
  565.     instanceVariableNames: ''!
  566.  
  567.  
  568. !IconManager class methodsFor: 'view creation'!
  569.  
  570. openOnDir: aDir
  571.     " open an icon browser on the directory named aDir"
  572.     "IconManager openOnDir: '<directory name>'."
  573.  
  574.     | topView listView formView iconDictionary |
  575.     (Disk directoryNamed: aDir) exists 
  576.         ifFalse: [PopUpNotifier message:  'Error: directory does not exist'.
  577.                   ^nil].    
  578.     iconDictionary _ self new initDict: aDir.
  579.  
  580.     topView_StandardSystemView
  581.         model: iconDictionary
  582.         label: 'directory:',aDir
  583.         minimumSize: 50@50.
  584.     topView borderWidth: 1.
  585.  
  586.     listView_SelectionInListView
  587.         on:iconDictionary
  588.         aspect: #icon
  589.         change: #icon:
  590.         list: #iconList
  591.         menu: #iconMenu
  592.         initialSelection: #currentIcon.
  593.  
  594.     formView_IconEditorView
  595.         on: iconDictionary
  596.         aspect: #form
  597.         menu: #iconMenu.
  598.  
  599.     topView addSubView: listView
  600.         in: (0@0 extent: 1@0.6)
  601.         borderWidth: 1.
  602.     topView addSubView: formView
  603.         in: (0@0.6 extent: 1@0.4)
  604.         borderWidth: 1.
  605.  
  606.     topView controller open! !
  607.  
  608.  
  609. !IconManager class methodsFor: 'retrieving forms'!
  610.  
  611. formToCursor: aForm
  612.  
  613.     ^Cursor extent: aForm extent 
  614.                 fromArray: aForm bits 
  615.                 offset: aForm offset!
  616.  
  617. getCursor: iconName fromDirectory: dirName
  618.     " retrieve an icon from disk "
  619.  
  620.     | directory |
  621.     directory _ Disk directoryNamed: dirName.
  622.     directory exists 
  623.         ifFalse: [self error:  'Forms directory ',dirName,' does not exist'.
  624.                   ^nil].
  625.     directory namesDo: 
  626.         [:each | (iconName match: each)
  627.                     ifTrue: [^self formToCursor: (Form readFrom: dirName,'/',iconName)]].
  628.     self error:  'Cannot find icon ',iconName,' in directory ',dirName.
  629.     ^nil!
  630.  
  631. getIcon: iconName fromDirectory: dirName
  632.     " retrieve an icon from disk  "
  633.  
  634.     | directory |
  635.     directory _ Disk directoryNamed: dirName.
  636.     directory exists 
  637.         ifFalse: [self error:  'Forms directory ',dirName,' does not exist'.
  638.                   ^nil].
  639.     directory namesDo: 
  640.         [:each | (iconName match: each)
  641.                     ifTrue: [^Form readFrom: dirName,'/',iconName]].
  642.     self error:  'Cannot find icon ',iconName,' in directory ',dirName.
  643.     ^nil! !
  644.  
  645.  
  646. FormView subclass: #IconEditorView
  647.     instanceVariableNames: 'clippingRectangle formMsg menuMsg scrollOffset '
  648.     classVariableNames: ''
  649.     poolDictionaries: ''
  650.     category: 'Icon-Tools'!
  651. IconEditorView comment:
  652. 'I am the view in an icon browser that provides a view of the icon.'!
  653.  
  654.  
  655. !IconEditorView methodsFor: 'updating'!
  656.  
  657. update: aSymbol 
  658.     | form |
  659.     aSymbol == formMsg
  660.         ifTrue: [form _ self getForm.
  661.                 form isNil
  662.                     ifFalse:[self scrollOffset:0@0.  
  663.                             self displayView].
  664.             super update: aSymbol]! !
  665.  
  666.  
  667. !IconEditorView methodsFor: 'private'!
  668.  
  669. clippingRectangle
  670.     ^clippingRectangle!
  671.  
  672. clippingRectangle: aRect
  673.     clippingRectangle_aRect!
  674.  
  675. compositionRectangle
  676.     ^Rectangle origin: self scrollOffset+self clippingRectangle origin extent: self getForm extent!
  677.  
  678. on: anObject aspect: m1 menu: m4
  679.     self model: anObject.
  680.     formMsg _ m1.
  681.     menuMsg _ m4.
  682.     self initialize!
  683.  
  684. scrollOffset
  685.     ^scrollOffset!
  686.  
  687. scrollOffset: aPoint
  688.     scrollOffset_aPoint! !
  689.  
  690.  
  691. !IconEditorView methodsFor: 'window access'!
  692.  
  693. defaultWindow 
  694.     ^(Rectangle origin: 0 @ 0 extent: self getForm extent)
  695.         expandBy: borderWidth! !
  696.  
  697.  
  698. !IconEditorView methodsFor: 'displaying'!
  699.  
  700. display
  701.     self isUnlocked ifTrue: [self scrollOffset:0@0].
  702.     self displayBorder.
  703.     self displayView.
  704.     self noSelectionSelected.!
  705.  
  706. displayView 
  707.     self clippingRectangle: self insetDisplayBox.
  708.     self clearInside: Form lightGray.
  709.     insideColor == nil ifFalse: [Display fill: self insetDisplayBox mask: insideColor].
  710.     (self getForm)
  711.         displayOn: Display
  712.         at: (self insetDisplayBox origin) + self scrollOffset
  713.         clippingBox: self clippingRectangle
  714.         rule: self rule
  715.         mask: self mask! !
  716.  
  717.  
  718. !IconEditorView methodsFor: 'controller access'!
  719.  
  720. defaultControllerClass
  721.     ^IconEditorController! !
  722.  
  723.  
  724. !IconEditorView methodsFor: 'scrolling'!
  725.  
  726. scrollBy: aPoint 
  727.      "The x component of aPoint specifies the amount of scrolling in the x direction; 
  728.     the y component specifies the amount of scrolling in the y direction. The amounts 
  729.     are specified in the receiver's local coordinate system."
  730.  
  731.     self scrollOffset: self scrollOffset + aPoint.
  732.     self display! !
  733.  
  734.  
  735. !IconEditorView methodsFor: 'adaptor'!
  736.  
  737. getForm
  738.     | form |
  739.     formMsg == nil ifTrue: [^nil].
  740.     form _ model perform: formMsg.
  741.     ^ form! !
  742.  
  743. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  744.  
  745. IconEditorView class
  746.     instanceVariableNames: ''!
  747.  
  748.  
  749. !IconEditorView class methodsFor: 'instance creation'!
  750.  
  751. on: anObject aspect: aspectMsg menu: menuMsg
  752.     "Create a 'pluggable' (see class comment) formView viewing anObject.
  753.     aspectMsg is sent to read the current form in the model.
  754.         It is also used as the changed: parameter for this view."
  755. | pfView |
  756.     pfView_self new on: anObject aspect: aspectMsg menu: menuMsg.
  757.     pfView scrollOffset: 0@0.
  758.     ^pfView! !
  759.  
  760.